﻿/// <reference path="jquery-1.3.2-vsdoc.js"/>
/// <reference path="jquery-ui-personalized-1.5.3.js"/>
/*
COPYRIGHT (C) 2009 EPISERVER AB

THIS FILE IS PART OF SCRUM DASHBOARD.

SCRUM DASHBOARD IS FREE SOFTWARE: YOU CAN REDISTRIBUTE IT AND/OR MODIFY IT UNDER THE TERMS OF 
THE GNU LESSER GENERAL PUBLIC LICENSE VERSION v2.1 AS PUBLISHED BY THE FREE SOFTWARE FOUNDATION.

SCRUM DASHBOARD IS DISTRIBUTED IN THE HOPE THAT IT WILL BE USEFUL, BUT WITHOUT ANY WARRANTY; WITHOUT
EVEN THE IMPLIED WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. SEE THE GNU LESSER
GENERAL PUBLIC LICENSE FOR MORE DETAILS.

YOU SHOULD HAVE RECEIVED A COPY OF THE GNU LESSER GENERAL PUBLIC LICENSE ALONG WITH SCRUM DASHBOARD. 
IF NOT, SEE <HTTP://WWW.GNU.ORG/LICENSES/>.
*/

var db = {
    moveElement: null, originalElement: null, isDragging: false, isMousePressed: false, lastMouseOverCell: null, originalWorkRemaining: '',
    currentTableRow: null, insertTarget: null, oldState: null, newState: null,
    changeTimeID: null, showChangeTimeAlert: false, changeTimeTarget: null, assignedTo: null,

    //Click on Work Remaining to change the time
    changeTime: function(targetEl, id)
    {
        if (db.showChangeTimeAlert)
            return;

        target = $(targetEl);

        var input = $('<input type="text" style="text-align:right" value="' + target.html() + '" style="width:20px;" />');

        db.changeTimeTarget = targetEl;
        db.changeTimeID = id;
        db.showChangeTimeAlert = true;
        db.originalWorkRemaining = target.clone().get(0);

        target.keypress(db.changeTimeKeyPress);
        $(document).mousedown(db.clickToCancelChangeTime);

        try {
            target.empty();
            target.append(input);
            input.focus();
        } catch (err) { }
    },

    init: function()
    {
        $('body').mousedown(db.startDragWorkItem);
        $('body').mousemove(db.draggingWorkItem);
        $('body').mouseup(db.stopDragWorkItem);
    },

    //Handles click outside input box
    clickToCancelChangeTime: function(ev)
    {
        if (ev.target == db.changeTimeTarget || ev.target == db.changeTimeTarget.firstChild)
            return false;

        $(db.changeTimeTarget).html($(db.originalWorkRemaining).html());
        db.cancelChangeTime();
    },

    //Handles keypress when user is changing Work Remaining
    changeTimeKeyPress: function(ev)
    {
        var target = $(ev.target);
        var pattern = new RegExp("^[0-9]{1,3}$");
        var keynum = ev.which;

        if (keynum == Sys.UI.Key.enter) {
            if (pattern.test(target.val())) {
                var time = parseFloat(target.val());
                if (target.parent() != null)
                    target.parent().html(time.toString());

                var proxy = new ScrumDashboard.AjaxService();
                proxy.ChangeTime(db.changeTimeID, time, db.changeTimeSuccess, db.changeTimeFailed, null);

                db.cancelChangeTime();
            } else {
                alert('Only number between 0-999!');
            }
            return false;
        }
        if (keynum == Sys.UI.Key.esc) {
            $(db.changeTimeTarget).html($(db.originalWorkRemaining).html());
            db.cancelChangeTime();
            return false;
        }
    },

    //Webservice callback on success
    changeTimeSuccess: function(result)
    { },

    //Webservice callback on fail
    changeTimeFailed: function(error)
    {
        alert(error.get_message());
    },

    //Handles cancellation of change time
    cancelChangeTime: function()
    {
        $(db.changeTimeTarget).unbind('keypress', db.changeTimeKeyPress);
        $(document).unbind('mousedown', db.clickToCancelChangeTime);
        db.showChangeTimeAlert = false;
        db.changeTimeTarget = null;
    },

    //Mouse is pressed on a Work Item
    startDragWorkItem: function(ev)
    {
        if (ev.target.tagName == 'A' || ev.target.tagName == 'INPUT' || db.showChangeTimeAlert) {
            return;
        }

        if (db.isDragging) {
            return;
        }

        var dragBox = $(ev.target).parents('.dragItem');
        if (dragBox.size() != 1)
            return;

        db.isMousePressed = true;
        db.moveElement = dragBox.get(0);
        db.currentTableRow = dragBox.parents("tr").get(0);
        $('body').disableSelection();
    },

    //Work Item is being dragged
    draggingWorkItem: function(ev)
    {
        if (!db.isMousePressed || db.moveElement == null) {
            return;
        }

        if (db.isMousePressed && !db.isDragging) {
            db.isDragging = true;

            db.originalElement = $(db.moveElement).clone(true).replaceAll($(db.moveElement));
            db.moveElement.style.position = 'absolute';
            $(db.originalElement).css('opacity', '0');
            $(db.moveElement).css('opacity', '0.6').appendTo('body');
        }

        db.moveElement.style.top = ev.pageY + 1 + 'px';
        db.moveElement.style.left = ev.pageX + 1 + 'px';

        if (db.lastMouseOverCell)
            db.lastMouseOverCell.css('background-color', '');

        var targetCell = $(ev.target).parents('.DropTarget').andSelf().filter('td');
        if (targetCell.size() == 0) {
            return;
        }

        if (targetCell.parents('tr').get(0) == db.currentTableRow) {
            targetCell.css('background-color', '#eeeeee');
            db.lastMouseOverCell = targetCell;
        }
        else {
            db.lastMouseOverCell = null;
        }
    },

    //Dragged Work Item is being released somewhere
    stopDragWorkItem: function(ev)
    {
        if (!db.isMousePressed) {
            return;
        }
        db.isMousePressed = false;
        $('body').enableSelection();

        if (!db.isDragging || db.moveElement == null) {
            return;
        }

        db.isDragging = false;

        var target = $(ev.target);
        var targetCellQuery = target.parents('.DropTarget').andSelf().filter('td');
        if (targetCellQuery.size() == 0) {
            db.resetDragBox();
            return;
        }

        var targetCell = targetCellQuery.get(0);
        db.insertTarget = targetCell;

        //Validate correct drop location
        if (targetCell.parentNode != db.currentTableRow) {
            db.resetDragBox();
            return;
        }

        //Last CSS class is State of cell
        var cssArray = targetCell.className.split(" ");
        var itemStatus = null;
        for (var i = 0; i < cssArray.length; i++) {
            if (cssArray[i].startsWith('State-')) {
                itemStatus = cssArray[i].substring(6);
                break;
            }
        }

        if (itemStatus != null && db.isAllowedStateTransition($(db.moveElement).attr('sbState'), itemStatus)) {
            db.newState = itemStatus;
            var proxy = new ScrumDashboard.AjaxService();
            proxy.MoveToState($(db.moveElement).attr('sbId'), itemStatus, db.onMoveToStateSuccess, db.onMoveToStateFailed, null);
        }
        else {
            db.resetDragBox();
        }
    },

    //Reset dragged Work Item
    resetDragBox: function()
    {
        if (db.moveElement != null) {
            $(db.moveElement).replaceAll($(db.originalElement)).css({ position: 'relative', top: 0, left: 0, opacity: '1' });
            $(db.originalElement).remove();
            db.originalElement = null;
            db.moveElement = null;
        }

        if (db.lastMouseOverCell != null) {
            db.lastMouseOverCell.css('background-color', '');
            db.lastMouseOverCell = null;
        }
    },

    //Close the dialog (called from AssignTo.ascx)
    closeAssignedToDialog: function()
    {
        hideAssignToDialog($(db.moveElement).attr('sbId'));
    },

    //Callback from webservice when move to state succeeded
    onMoveToStateSuccess: function(result)
    {
        var j = $(db.moveElement);
        j.attr('sbState', db.newState);
        j.css({ opacity: '1', position: 'relative', left: 0, top: 0 });
        j.appendTo($(db.insertTarget));

        if (!j.hasClass('ItemUnplanned')) {
            j.removeClass('Item' + db.oldState);
            j.addClass('Item' + db.newState);
        }

        $(db.originalElement).remove();

        if (j.attr('sbAssignedTo') == '') {
            showAssignToDialog(j.attr('sbId'), true);
        }
    },

    //Callback from webservice when move to state failed
    onMoveToStateFailed: function(error)
    {
        db.resetDragBox();
        alert(error.get_message());
    },

    //Called to assign the currently dropped work item to a specific user (called from AssignTo.ascx)
    assignToUser: function(name)
    {
        var workitemID = $(db.moveElement).attr('sbId')
        var state = $(db.moveElement).attr('sbState');
        var assignedTo = name;
        db.assignedTo = name;

        var proxy = new ScrumDashboard.AjaxService();
        proxy.AssignTo(workitemID, state, assignedTo, db.assignToSuccess, db.assignFailed, null);

        hideAssignToDialog();
    },

    //Callback from webservice when assign to user succeeded
    assignToSuccess: function(result)
    {
        var changeAssign = $('#assignedTO' + $(db.moveElement).attr('sbId').toString());
        var name = db.assignedTo;

        $(db.moveElement).attr('sbAssignedTo',name);
        changeAssign.text(result.Initials);

        db.assignedTo = null;
    },

    //Callback from webservice when assign to user failed
    assignFailed: function(error)
    {
        alert(error.get_message());
    },

    //Check if it is allowed to move between states
    isAllowedStateTransition: function(fromState, toState)
    {
        if (fromState == 'NotDone' && toState == 'InProgress')
            return true;

        if (fromState == 'ReadyForTest' && (toState == 'Done' || toState == 'InProgress'))
            return true;

        if (fromState == 'InProgress' && (toState == 'ReadyForTest' || toState == 'Done'))
            return true;

        if (fromState == 'Done' && toState == 'InProgress')
            return true;

        return false;
    }
}

$(db.init);
